﻿using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;

namespace YBOT_Field_Control
{
    public static class Game
    {
        #region Board and Relay Variables
        static public int redLED = 1;
        static public int greenLED = 2;
        static public int lockLED = 3;
        static public int banditOffRelay = 7;
        static public int banditResetRelay = 6;
        static public int banditScoreRelay = 8;
        static public int bell = 2;
        static public int buzzer = 3;
        static public int controllerRelay = 4;
        static public int controlBoard = 15;
        static public int greenBandit = 11;
        static public int redBandit = 12;
        static public int redControlTower = 3;
        static public int greenControlTower = 8;
        static public int yellowDiceTower = 3;
        static public int blueDiceTower = 8;
        static public string time = DateTime.Now.Hour.ToString() + "_" + DateTime.Now.Minute.ToString() + "_" + DateTime.Now.Second.ToString();
        static public string gamePath = y1w.YBOTFilePath() + @"\Logs\Games_" + time;    //Sets path for game files

        #endregion

        #region Game and Scoring Variables
        public static int gameCycleCount = 0;
        public static int redScore = 0;
        public static int greenScore = 0;
        public static int jackpot = 0;
        static int bluediceNum = 0;
        static int yellowdiceNum = 0;
        static bool bluelock = false;
        static bool yellowlock = false;
        static bool blueDiceReset = false;
        static bool yellowDiceReset = false;
        static byte blueDiceTowerBuffer = 0;
        static byte yellowDiceTowerBuffer = 0;

        public static bool gameDone = false;
        public static bool STOP = false;
        #endregion

        public static void GameStartUp()
        {
            //Reset all variables
            bluediceNum = 0;
            yellowdiceNum = 0;
            bluelock = false;
            yellowlock = false;
            blueDiceReset = true;
            yellowDiceReset = true;
            jackpot = 0;
            redScore = 0;
            greenScore = 0;
            blueDiceTowerBuffer = 0x0C;
            yellowDiceTowerBuffer = 0x0C;


            y1w.AllRelaysOn(11);
            y1w.AllRelaysOn(12);
            y1w.AllRelaysOff(11);
            y1w.AllRelaysOff(12);

            //Ring bell
            y1w.RelayOn(bell, controlBoard);
            y1w.RelayOff(bell, controlBoard);
            Thread.Sleep(300);
            y1w.RelayOn(bell, controlBoard);
            y1w.RelayOff(bell, controlBoard);
            GameLog("Bell");

            //Set all towers to a known state

            y1w.AllTowersOn();
            AllTowersOffSafe();
            GameLog("All Towers Off");

            y1w.SetTowerState(yellowDiceTowerBuffer, yellowDiceTower);
            y1w.SetTowerState(blueDiceTowerBuffer, blueDiceTower);
            GameLog("Blue Dice Tower & Green Control On /r/n Yellow Dice Tower & Red Control On");
        }

        public static void GameShutDown()
        {
            yellowDiceTowerBuffer = y1w.BuildRelayState(controllerRelay, 0, yellowDiceTowerBuffer);
            blueDiceTowerBuffer = y1w.BuildRelayState(controllerRelay, 0, blueDiceTowerBuffer);
            y1w.SetTowerState(yellowDiceTowerBuffer, yellowDiceTower);
            y1w.SetTowerState(blueDiceTowerBuffer, blueDiceTower);

            MidTower();                     //Check 1 arm bandit status
            DiceTower();                    //Check dice tower status
            ChipTower();                    //Check chip tower status

            y1w.HubAllMainsOn();

            //Turn off all towers
            y1w.AllTowersOff();
            GameLog("All Towers Off");
            y1w.RelayOn(banditOffRelay, greenBandit);
            y1w.RelayOn(banditOffRelay, redBandit);
            GameLog("1 arm bandits off");

            //Sound buzzer
            y1w.RelayOn(buzzer, controlBoard);
            Thread.Sleep(750);
            y1w.RelayOff(buzzer, controlBoard);
            GameLog("buzzer");
        }

        public static void MainGame()
        {
            //Try and create game path if it doesn't exist; set as null if it can't
            try
            {
                if (!Directory.Exists(gamePath)) Directory.CreateDirectory(gamePath);
            }
            catch
            {
                gamePath = null;
            }

            while (!STOP && !gameDone)          //Do loop until the game is over or stopped
            {
                y1w.HubAllOff();
                MidTower();                     //Check 1 arm bandit status
                DiceTower();                    //Check dice tower status
                ChipTower();                    //Check chip tower status
                Application.DoEvents();         //Do windows stuff
                return;                         //Return to control program
            }
        }

        public static void ChipTower()
        {
            if ((bluediceNum != 0 && blueDiceReset && !bluelock) || (yellowdiceNum != 0 && yellowDiceReset && !yellowlock))
            {
                y1w.SelectHubMain(1);
                y1w.SelectHubMain(2);

                #region Blue Towers
                if (bluediceNum != 0 && blueDiceReset && !bluelock)
                {
                    if (bluediceNum == 1)
                    {
                        blueDiceReset = false;
                        GameLog("Blue Chip Tower# 1 = Locked");
                        y1w.RelayOn(lockLED, 7);
                        y1w.RelayStatus(7);

                        if (y1w.Status(greenLED, 7))
                        {
                            greenScore = greenScore + jackpot;
                            GameLog("Green Scored: GreenScore = " + greenScore.ToString());
                        }
                        else if (y1w.Status(redLED, 7))
                        {
                            redScore = redScore + jackpot;
                            GameLog("Red Scored: RedScore = " + greenScore.ToString());
                        }
                        if (jackpot > 0) jackpot--;
                        GameLog("Jackpot = " + jackpot.ToString());
                    }
                    else if (bluediceNum == 2)
                    {
                        blueDiceReset = false;
                        GameLog("Blue Chip Tower# 2 = Locked");
                        y1w.RelayOn(lockLED, 6);
                        y1w.RelayStatus(6);

                        if (y1w.Status(greenLED, 6))
                        {
                            greenScore = greenScore + jackpot;
                            GameLog("Green Scored: GreenScore = " + greenScore.ToString());
                        }
                        else if (y1w.Status(redLED, 6))
                        {
                            redScore = redScore + jackpot;
                            GameLog("Red Scored: RedScore = " + greenScore.ToString());
                        }
                        if (jackpot > 0) jackpot--;
                        GameLog("Jackpot = " + jackpot.ToString());
                    }
                    else if (bluediceNum == 3)
                    {
                        blueDiceReset = false;
                        GameLog("Blue Chip Tower# 3 = Locked");
                        y1w.RelayOn(lockLED, 5);
                        y1w.RelayStatus(5);

                        if (y1w.Status(greenLED, 5))
                        {
                            greenScore = greenScore + jackpot;
                            GameLog("Green Scored: GreenScore = " + greenScore.ToString());
                        }
                        else if (y1w.Status(redLED, 5))
                        {
                            redScore = redScore + jackpot;
                            GameLog("Red Scored: RedScore = " + greenScore.ToString());
                        }
                        if (jackpot > 0) jackpot--;
                        GameLog("Jackpot = " + jackpot.ToString());
                    }
                    else if (bluediceNum == 4)
                    {
                        blueDiceReset = false;
                        GameLog("Blue Chip Tower# 4 = Locked");
                        y1w.RelayOn(lockLED, 4);
                        y1w.RelayStatus(4);

                        if (y1w.Status(greenLED, 4))
                        {
                            greenScore = greenScore + jackpot;
                            GameLog("Green Scored: GreenScore = " + greenScore.ToString());
                        }
                        else if (y1w.Status(redLED, 4))
                        {
                            redScore = redScore + jackpot;
                            GameLog("Red Scored: RedScore = " + greenScore.ToString());
                        }
                        if (jackpot > 0) jackpot--;
                        GameLog("Jackpot = " + jackpot.ToString());
                    }
                    else
                    {
                        //More to come
                    }
                }
                #endregion

                #region Yellow Towers
                if (yellowdiceNum != 0 && yellowDiceReset && !yellowlock)
                {
                    if (yellowdiceNum == 1)
                    {
                        yellowDiceReset = false;
                        GameLog("Yellow Chip Tower# 1 = Locked");
                        y1w.RelayOn(lockLED, 2);
                        y1w.RelayStatus(2);

                        if (y1w.Status(greenLED, 2))
                        {
                            greenScore = greenScore + jackpot;
                            GameLog("Green Scored: GreenScore = " + greenScore.ToString());
                        }
                        else if (y1w.Status(redLED, 2))
                        {
                            redScore = redScore + jackpot;
                            GameLog("Red Scored: RedScore = " + greenScore.ToString());
                        }
                        if (jackpot > 0) jackpot--;
                        GameLog("Jackpot = " + jackpot.ToString());
                    }
                    else if (yellowdiceNum == 2)
                    {
                        yellowDiceReset = false;
                        GameLog("Yellow Chip Tower# 2 = Locked");
                        y1w.RelayOn(lockLED, 1);
                        y1w.RelayStatus(1);

                        if (y1w.Status(greenLED, 1))
                        {
                            greenScore = greenScore + jackpot;
                            GameLog("Green Scored: GreenScore = " + greenScore.ToString());
                        }
                        else if (y1w.Status(redLED, 1))
                        {
                            redScore = redScore + jackpot;
                            GameLog("Red Scored: RedScore = " + greenScore.ToString());
                        }
                        if (jackpot > 0) jackpot--;
                        GameLog("Jackpot = " + jackpot.ToString());
                    }
                    else if (yellowdiceNum == 3)
                    {
                        yellowDiceReset = false;
                        GameLog("Yellow Chip Tower# 3 = Locked");
                        y1w.RelayOn(lockLED, 10);
                        y1w.RelayStatus(10);

                        if (y1w.Status(greenLED, 10))
                        {
                            greenScore = greenScore + jackpot;
                            GameLog("Green Scored: GreenScore = " + greenScore.ToString());
                        }
                        else if (y1w.Status(redLED, 10))
                        {
                            redScore = redScore + jackpot;
                            GameLog("Red Scored: RedScore = " + greenScore.ToString());
                        }
                        if (jackpot > 0) jackpot--;
                        GameLog("Jackpot = " + jackpot.ToString());
                    }
                    else if (yellowdiceNum == 4)
                    {
                        yellowDiceReset = false;
                        GameLog("Yellow Chip Tower# 4 = Locked");
                        y1w.RelayOn(lockLED, 9);
                        y1w.RelayStatus(9);

                        if (y1w.Status(greenLED, 9))
                        {
                            greenScore = greenScore + jackpot;
                            GameLog("Green Scored: GreenScore = " + greenScore.ToString());
                        }
                        else if (y1w.Status(redLED, 9))
                        {
                            redScore = redScore + jackpot;
                            GameLog("Red Scored: RedScore = " + greenScore.ToString());
                        }
                        if (jackpot > 0) jackpot--;
                        GameLog("Jackpot = " + jackpot.ToString());
                    }
                    else
                    {
                        //More to come
                    }
                }
                #endregion

                y1w.HubAllOff();
            }
        }

        public static void DiceTower()
        {
            bool blueClear = false;
            bool yellowClear = false;

            #region Yellow Dice Tower


            y1w.SelectHubMain(1);
            y1w.RelayStatus(yellowDiceTower);
            string yellowstatus = null;
            string bluestatus = null;

            yellowdiceNum = DiceNumber(yellowDiceTower);  //Get the number on the yellow dice
                if (yellowdiceNum == 0 && bluediceNum != 6)
                {
                    yellowDiceReset = true;
                    yellowDiceTowerBuffer = 0x0C; // y1w.BuildRelayState(lockLED, 1, yellowDiceTowerBuffer);
                    y1w.SetTowerState(yellowDiceTowerBuffer, yellowDiceTower);
                    yellowlock = false;
                    yellowstatus = yellowstatus + " - UNLOCKED Yellow Dice Tower";
                }
                else if ((yellowdiceNum == 6 || bluediceNum == 6) && !yellowlock)
                {
                    yellowDiceTowerBuffer = 0x08; //y1w.BuildRelayState(lockLED, 0, yellowDiceTowerBuffer);
                    y1w.SetTowerState(yellowDiceTowerBuffer, yellowDiceTower);
                    yellowlock = true;
                    yellowClear = true;
                    yellowstatus = yellowstatus + " - Yellow Tower Locked";
                }
        
            y1w.SelectHubOff(1);
            #endregion

            #region Blue Dice Tower

            y1w.SelectHubMain(2);
            y1w.RelayStatus(blueDiceTower);

            bluediceNum = DiceNumber(blueDiceTower);    //Get the number on the blue dice

                if (bluediceNum == 0 && yellowdiceNum != 5)
                {
                    bluelock = false;
                    blueDiceReset = true;
                    blueDiceTowerBuffer = 0x0C; //y1w.BuildRelayState(lockLED, 1, blueDiceTowerBuffer);
                    y1w.SetTowerState(blueDiceTowerBuffer, blueDiceTower);
                    bluestatus = bluestatus + " - UNLOCKED Blue Dice Tower";
                }
                else if ((bluediceNum == 5 || yellowdiceNum == 5) && !bluelock)
                {
                    blueDiceTowerBuffer = 0x08; //y1w.BuildRelayState(lockLED, 0, blueDiceTowerBuffer);
                    y1w.SetTowerState(blueDiceTowerBuffer, blueDiceTower);
                    bluelock = true;
                    blueClear = true;
                    bluestatus = bluestatus + " - Blue Tower Locked";
                }
            y1w.SelectHubOff(2);
            #endregion

            UnlockTowers(blueClear, yellowClear);

            GameLog("Blue Dice = " + bluediceNum.ToString() + bluestatus + "/r/n/" + "Yellow Dice = " + yellowdiceNum.ToString() + yellowstatus);
        }

        public static void MidTower()
        {
            y1w.SelectHubMain(3);
            byte relaybuffer = 0;
            relaybuffer = y1w.BuildRelayState(banditResetRelay, 1, relaybuffer);

            if (jackpot < 10)
            {
                y1w.RelayStatus(greenBandit);

                if (!y1w.Status(banditScoreRelay, greenBandit) && y1w.Tower[greenBandit].stat != 0)
                {
                    y1w.SetTowerState(relaybuffer, greenBandit);
                    greenScore = greenScore + 2;
                    if (jackpot < 10)
                    {
                        jackpot++;
                    }
                    GameLog("Green Scored: Bandit: GreenScore = " + greenScore.ToString() + " Jackpot = " + jackpot.ToString());
                }
                else
                {
                    if (y1w.Status(banditResetRelay, greenBandit)) y1w.AllRelaysOff(greenBandit);
                }

                y1w.RelayStatus(redBandit);

                if (!y1w.Status(banditScoreRelay, redBandit) && y1w.Tower[redBandit].stat != 0)
                {
                    y1w.SetTowerState(relaybuffer, redBandit);
                    redScore = redScore + 2;
                    if (jackpot < 10)
                    {
                        jackpot++;
                    }
                    GameLog("Red Scored: Bandit: RedScore = " + greenScore.ToString() + " Jackpot = " + jackpot.ToString());
                }
                else
                {
                    if (y1w.Status(banditResetRelay, redBandit)) y1w.AllRelaysOff(redBandit);
                }
            }

            if (jackpot < 10)
            {
                if (y1w.Status(banditOffRelay, redBandit))
                {
                    y1w.AllRelaysOff(redBandit);
                }
                if (y1w.Status(banditOffRelay, greenBandit))
                {
                    y1w.AllRelaysOff(greenBandit);
                }
                GameLog("Jackpot = " + jackpot.ToString() + " -> Bandits ON");
            }
            else
            {
                relaybuffer = 0;
                relaybuffer = y1w.BuildRelayState(banditOffRelay, 1, relaybuffer);
                if (!y1w.Status(banditOffRelay, redBandit))
                {
                    y1w.SetTowerState(relaybuffer, redBandit);
                }
                if (!y1w.Status(banditOffRelay, greenBandit))
                {
                    y1w.SetTowerState(relaybuffer, greenBandit);
                }
                GameLog("Jackpot = " + jackpot.ToString() + " -> Bandits OFF");
            }

            y1w.SelectHubOff(3);

        }

        /// <summary>
        /// Used to get the number on the dice of a given tower
        /// </summary>
        /// <param name="towerNum">Tower number</param>
        /// <returns>Return an interger</returns>
        public static int DiceNumber(int towerNum)
        {
            //Used a binary counter on relays 6,7,8 to calculate the dice number
            if (!y1w.Status(6, towerNum) && !y1w.Status(7, towerNum) && y1w.Status(8, towerNum)) return 1;
            else if (!y1w.Status(6, towerNum) && y1w.Status(7, towerNum) && !y1w.Status(8, towerNum)) return 2;
            else if (!y1w.Status(6, towerNum) && y1w.Status(7, towerNum) && y1w.Status(8, towerNum)) return 3;
            else if (y1w.Status(6, towerNum) && !y1w.Status(7, towerNum) && !y1w.Status(8, towerNum)) return 4;
            else if (y1w.Status(6, towerNum) && !y1w.Status(7, towerNum) && y1w.Status(8, towerNum)) return 5;
            else if (y1w.Status(6, towerNum) && y1w.Status(7, towerNum) && !y1w.Status(8, towerNum)) return 6;
            else return 0;
        }

        public static void UnlockTowers(bool blueClear, bool yellowClear)
        {
            y1w.SelectHubMain(1);
            y1w.SelectHubMain(2);
            if (blueClear)
            {
                y1w.AllRelaysOff(4);
                y1w.AllRelaysOff(5);
                y1w.AllRelaysOff(6);
                y1w.AllRelaysOff(7);
                blueDiceReset = false;
                GameLog("RESET Blue Chip Towers");
            }
            if (yellowClear)
            {
                y1w.AllRelaysOff(1);
                y1w.AllRelaysOff(2);
                y1w.AllRelaysOff(9);
                y1w.AllRelaysOff(10);
                yellowDiceReset = false;
                GameLog("RESET Yellow Chip Towers");
            }
            y1w.HubAllOff();
        }

        public static void AllTowersOffSafe()
        {
            byte relayBuffer = 0;
            relayBuffer = 0x08; // y1w.BuildRelayState(controllerRelay, 1, relayBuffer);

            y1w.AllRelaysOff(1);
            y1w.AllRelaysOff(2);
            y1w.SetTowerState(relayBuffer, 3);
            y1w.AllRelaysOff(4);
            y1w.AllRelaysOff(5);
            y1w.AllRelaysOff(6);
            y1w.AllRelaysOff(7);
            y1w.SetTowerState(relayBuffer, 8);
            y1w.AllRelaysOff(9);
            y1w.AllRelaysOff(10);
            y1w.AllRelaysOff(11);
            y1w.AllRelaysOff(12);

        }

        /// <summary>
        /// Writes text to log file
        /// </summary>
        /// <param name="text">Text as string</param>
        public static void GameLog(string text)
        {
            string file = "\\Game#" + gameCycleCount.ToString() + ".txt";
            try
            {
                if (!Directory.Exists(gamePath)) Directory.CreateDirectory(gamePath);
                string date = DateTime.Today.ToShortDateString();
                string time = DateTime.Now.ToLongTimeString() + ":" + DateTime.Now.Millisecond.ToString();
                text = (date + " " + time + " " + text);
                FileStream fs = new FileStream((gamePath + file), FileMode.Append, FileAccess.Write, FileShare.Write);
                fs.Close();
                StreamWriter sw = new StreamWriter((gamePath + file), true, Encoding.ASCII);
                sw.WriteLine(text);
                sw.Close();
            }
            catch
            {
                return;
            }
        }

    }
}
